package com.zhiche.lisa.integration.inteface.otm;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.lisa.json.JSONUtil;
import com.lisa.syslog.SysLogUtil;
import com.lisa.syslog.model.SysLogDataPo;
import com.qiniu.storage.model.DefaultPutRet;
import com.zhiche.lisa.core.enums.*;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.supports.RestfulResponse;
import com.zhiche.lisa.core.utils.HttpClientUtil;
import com.zhiche.lisa.core.utils.XmlUtil;
import com.zhiche.lisa.core.utils.qiniu.util.QiniuUtils;
import com.zhiche.lisa.integration.anno.AnnoUtil;
import com.zhiche.lisa.integration.dao.model.*;
import com.zhiche.lisa.integration.dto.carrier.*;
import com.zhiche.lisa.integration.dto.order.OTMEvent;
import com.zhiche.lisa.integration.dto.redisLog.LogExportPo;
import com.zhiche.lisa.integration.service.*;
import org.dom4j.Document;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * Created by zhaoguixin on 2018/7/22.
 */
@Service
public class OtmEventService {

    private Logger LOGGER = LoggerFactory.getLogger(getClass());

    private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");

    @Autowired
    private IExportLogService exportLogService;
    @Autowired
    private IProcessCallBackService processCallBackService;
    @Autowired
    private IExportLogHistoryService exportLogHistoryService;
    @Autowired
    private IImportLogService importLogService;
    @Autowired
    private IImportLogHistoryService importLogHistoryService;
    @Autowired
    private IPushSubSystemService pushSubSystemService;
    @Autowired
    private IImportLogService iImportLogService;


    @Value("${otm.url}")
    private String OTM_URL;

    @Value("${otm.event.callBackUrl}")
    private String CALL_BACK_URL;

    @Value("${logwire.url}")
    private String LOGWIRE_URL;

    @Value("${logRedis.isTest}")
    private boolean isTest;

    private static final String EVENT_URI = "/GC3/glog.integration.servlet.WMServlet";

    private static final String CALL_BACK_URI = "/event/callBack";

    private static final String CHECKIN_URI = "/interface/adapter/truck_register_sync";

    private static final String SHIP_DATA_FOR_BMS = "/shipTask/shipDataForBMS";

    /**
     * 导出Xml文本至TOM
     */
    public String exportXml2OTM(String exportKey, String type, Object dto) throws Exception {
        Date startDate = new Date();
        String eventXml = AnnoUtil.loadXml2String(dto);
        LOGGER.info("OtmEventService-->exportXml2OTM url:{},exportKey:{}",OTM_URL + EVENT_URI,exportKey);
        String requestResult = HttpClientUtil.post(OTM_URL + EVENT_URI, eventXml);
        LOGGER.info("OtmEventService-->exportXml2OTM result:{},exportKey:{}",requestResult,exportKey);
        //获取接口请求id
        requestResult = requestResult.replaceAll(" xmlns:ns2=\\\"http://xmlns.oracle.com/apps/gtm/transmission/v6.4\\\" xmlns=\\\"http://xmlns.oracle.com/apps/otm/transmission/v6.4\\\"", "");
        Document document = XmlUtil.parseByString(requestResult);
        String nodePath = "/TransmissionAck/EchoedTransmissionHeader/TransmissionHeader/ReferenceTransmissionNo";
        //得到根节点
        Element element = (Element) document.selectSingleNode(nodePath);
        //得到根节点的值
        String requestId = element.getText();
        Date endDate = new Date();

        ExportLogHistory exportLogHistory = new ExportLogHistory();
        exportLogHistory.setTargertSys("otm");
        exportLogHistory.setExportKey(exportKey);
        exportLogHistory.setType(type);
        exportLogHistory.setInterfaceUrl(OTM_URL + EVENT_URI);
        exportLogHistory.setExportStatus("1");
        exportLogHistory.setRequestId(requestId);
        exportLogHistory.setExportStartTime(startDate);
        exportLogHistory.setExportEndTime(endDate);

        Thread thread = new Thread() {
            public void run() {
                updateExportLogHistory(exportLogHistory, eventXml);
            }
        };
        thread.start();

        return requestId;
    }

    /**
     * 保存导出日志历史和数据内容
     */
    public void updateExportLogHistory(ExportLogHistory exportLogHistory, String dataContent) {
        String qiniuKey;
        try {
            Wrapper<ExportLog> ew = new EntityWrapper<>();
            ew.eq("targert_sys", exportLogHistory.getTargertSys());
            ew.eq("export_key", exportLogHistory.getExportKey());
            ew.eq("type", exportLogHistory.getType());
            ExportLog exportLog = exportLogService.selectOne(ew);
            if (Objects.nonNull(exportLog)) {
                Integer logId = exportLog.getId();
                BeanUtils.copyProperties(exportLogHistory, exportLog);
                exportLogHistory.setLogId(logId);
                exportLog.setId(logId);
                exportLog.setGmtCreate(null);
                exportLog.setGmtModified(null);
                exportLogHistoryService.insert(exportLogHistory);
                exportLogService.updateById(exportLog);
            } else {
                exportLog = new ExportLog();
                BeanUtils.copyProperties(exportLogHistory, exportLog);
                exportLogService.insert(exportLog);
                exportLogHistory.setLogId(exportLog.getId());
                exportLogHistoryService.insert(exportLogHistory);
            }

            String fileName = exportLogHistory.getTargertSys() + exportLogHistory.getType() +
                    exportLogHistory.getExportKey() + "_" + exportLogHistory.getLogId() + "_" + exportLogHistory.getId();
            DefaultPutRet putRet = QiniuUtils.uploadString(dataContent, fileName);
            qiniuKey = putRet.key;
            exportLogHistory.setDataStorageKey(qiniuKey);
            exportLog.setDataStorageKey(qiniuKey);

            exportLogHistoryService.updateById(exportLogHistory);
            exportLogService.updateById(exportLog);
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage());
        }
    }


    /**
     * 导出事件
     */
    public String exportEvent(OTMEvent paramDTO) throws Exception {
        String paramJson = JSONObject.toJSONString(paramDTO);
        LOGGER.info("integration-->EVENT 事件导出 param:{}", paramJson);
        if (StringUtils.isEmpty(paramDTO.getCallBackUrl())) {
            paramDTO.setCallBackUrl(CALL_BACK_URL + CALL_BACK_URI);
        }
        if (InterfaceEventEnum.BS_OP_DELIVERY.getCode().equals(paramDTO.getEventType())) {
            //增加wms推送发运推送TMS   tms司机发运走的另外接口
            deliveryToTMS(paramDTO, paramJson);
        }
        return exportXml2OTM(paramDTO.getExportKey(), paramDTO.getEventType(), paramDTO);
    }


    //增加wms推送发运推送TMS
    private void deliveryToTMS(OTMEvent paramDTO, String paramJson) {
        EntityWrapper<PushSubSystem> shipEW = new EntityWrapper<>();
        shipEW.eq("type", IntegrationURIEnum.SHIP_TMS.getCode())
                .orderBy("id", false);
        PushSubSystem subSystem = pushSubSystemService.selectOne(shipEW);
        if (subSystem != null) {
            new Thread(() -> {
                try {
                    LOGGER.info("integration-->EVENT 发运导出TMS url:{}, param:{}", subSystem.getUrl(), paramJson);

                    //记录事件导出已下发到日志系统
//                    addExportLogs(paramDTO, SHIP_DATA_FOR_BMS, 1, 1, "");

                    HttpClientUtil.postJson(subSystem.getUrl(), null, paramJson, subSystem.getSocketTimeOut());
                } catch (Exception e) {
                    LOGGER.error("integration-->EVENT 发运导出TMS 失败:{}", e);
                }
            }).start();
        }
    }

    /**
     * 添加日志记录到日志系统
     */
    public void addExportLogs(OTMEvent otmEvent, String uri, Integer dataStatus, Integer isSuc, String errCont) {
        try {
            if (Objects.nonNull(otmEvent)) {
                String tableIdx = RedisLogTypeEnum.EVENT_EXPORT.getCode();
                String sourceSystem = SystemEnum.INTEGRATION.getCode();
                String targetSystem = SystemEnum.OMS.getCode();
                // 来源、目标系统表示
                // 目标API标示
                String key = sourceSystem + SystemEnum.UNDERLINE.getCode() + targetSystem;
                String fKey = uri + SystemEnum.UNDERLINE.getCode() + otmEvent.getExportKey() + SystemEnum.UNDERLINE.getCode() + otmEvent.getEventType() + SystemEnum.UNDERLINE.getCode() + dataStatus;
                String dtoJson = JSONUtil.toJsonStr(otmEvent);
                // 业务相关实体类
                LogExportPo logExportPo = new LogExportPo(sourceSystem, targetSystem, otmEvent.getEventType(), uri, otmEvent.getShipmentId(),
                        otmEvent.getOrderReleaseId(), otmEvent.getVin(), otmEvent.getOrderReleaseId(), otmEvent.getExportKey(), dtoJson, isSuc, errCont, 1, 0, dataStatus);
                SysLogDataPo sysLogDataPo = new SysLogDataPo(tableIdx, JSONUtil.toJsonStr(logExportPo));
                SysLogUtil.addSysLogs(key, fKey, sysLogDataPo, isTest);
            }
        } catch (Exception e) {
            LOGGER.error("事件导出回传otm，添加日志异常" + e.getMessage());
        }
    }

    /**
     * 导出承运商
     */
    public String exportLsp(LspInfoDTO lspInfoDTO) throws Exception {
        if (StringUtils.isEmpty(lspInfoDTO.getCallBackUrl())) lspInfoDTO.setCallBackUrl(CALL_BACK_URL + CALL_BACK_URI);
        lspInfoDTO.setServiceType("公路");
        lspInfoDTO.setTransactionCode("IU");
        return exportXml2OTM(lspInfoDTO.getId().toString(), "50", lspInfoDTO);
    }

    /**
     * 导出车辆
     */
    public String exportVehicle(VehicleDTO vehicleDTO) throws Exception {
        if (StringUtils.isEmpty(vehicleDTO.getCallBackUrl())) {
            vehicleDTO.setCallBackUrl(CALL_BACK_URL + CALL_BACK_URI);
        }
        vehicleDTO.setTransactionCode("IU");
        if (TableStatusEnum.STATUS_Y.getCode().equalsIgnoreCase(vehicleDTO.getFleetTypeId())) {
            vehicleDTO.setFleetTypeId(vehicleDTO.getFleetTypeId().toUpperCase());
        } else {
            vehicleDTO.setFleetTypeId("");
        }
        return exportXml2OTM(vehicleDTO.getId().toString(), "51", vehicleDTO);
    }

    /**
     * 导出司机
     */
    public String exportDriver(DriverDTO driverDTO) throws Exception {
        if (StringUtils.isEmpty(driverDTO.getCallBackUrl())) {
            driverDTO.setCallBackUrl(CALL_BACK_URL + CALL_BACK_URI);
        }
        driverDTO.setTransactionCode("IU");
        return exportXml2OTM(driverDTO.getId().toString(), "52", driverDTO);
    }


    /**
     * 导出报班信息
     */
    public RestfulResponse<Object> exportDriverCheckin(DriverCheckinDTO driverCheckin) throws Exception {
        if (Objects.isNull(driverCheckin)) {
            throw new BaseException("报班不能为空");
        }

        if (Objects.nonNull(driverCheckin.getGmtCheckin())) {
            driverCheckin.setCheckinTime(formatter.format(driverCheckin.getGmtCheckin()));
        }
        if (Objects.nonNull(driverCheckin.getGmtExpLoad())) {
            driverCheckin.setExpLoadTime(formatter.format(driverCheckin.getGmtExpLoad()));
        }

        if (Objects.isNull(driverCheckin.getIsActive())) {
            driverCheckin.setIsActive(TableStatusEnum.STATUS_TRUE.getCode());
        }
        if (Objects.isNull(driverCheckin.getIsLongTerm())) {
            driverCheckin.setIsLongTerm(TableStatusEnum.STATUS_FALSE.getCode());
        }
        if (TableStatusEnum.STATUS_Y.getCode().equalsIgnoreCase(driverCheckin.getFleetTypeId())) {
            driverCheckin.setFleetTypeId(TableStatusEnum.STATUS_Y.getCode().toUpperCase());
        } else {
            driverCheckin.setFleetTypeId("");
        }

        Date startDate = new Date();

        String driverCheckinXml = AnnoUtil.loadXml2String(driverCheckin);
        LOGGER.info("OtmEventService-->exportDriverCheckin url:{},checkinId:{}",LOGWIRE_URL + CHECKIN_URI,driverCheckin.getId());
        String requestResult = HttpClientUtil.postUTF(LOGWIRE_URL + CHECKIN_URI, driverCheckinXml);
        LOGGER.info("OtmEventService-->exportDriverCheckin result:{},checkinId:{},",requestResult,driverCheckin.getId());
        JSONObject jsonObject = JSON.parseObject(requestResult);
        String messageType = jsonObject.get("messageType").toString();
        String message = null;
        if (Objects.nonNull(jsonObject.get("message"))) {
            message = jsonObject.get("message").toString();
        }

        RestfulResponse<Object> restfulResponse = new RestfulResponse<>();
        if (messageType.equals("success")) {
            restfulResponse.setCode(0);
            restfulResponse.setMessage(message);
        } else {

            restfulResponse.setCode(-1);
            restfulResponse.setMessage(message);
        }

        Date endDate = new Date();
        ExportLogHistory exportLogHistory = new ExportLogHistory();
        exportLogHistory.setTargertSys("otm");
        exportLogHistory.setExportKey(driverCheckin.getId().toString());
        exportLogHistory.setType("53");
        exportLogHistory.setInterfaceUrl(LOGWIRE_URL + CHECKIN_URI);
        exportLogHistory.setExportStatus(messageType);
        exportLogHistory.setExportRemarks(message);
        exportLogHistory.setExportStartTime(startDate);
        exportLogHistory.setExportEndTime(endDate);

        Thread thread = new Thread() {
            public void run() {
                updateExportLogHistory(exportLogHistory, driverCheckinXml);
            }
        };
        thread.start();

        return restfulResponse;
    }


    /**
     * OTM回调处理
     */
    public ProcessCallBack callBack(String callBackXml) {
        Document document = null;
        LOGGER.info("回调返回信息:{}", callBackXml);
        if (org.apache.commons.lang3.StringUtils.isEmpty(callBackXml)) {
            throw new BaseException("回调信息为空");
        }
        callBackXml = callBackXml.replaceAll
                (" xmlns:gtm=\"http://xmlns.oracle.com/apps/gtm/transmission/v6.4\" " +
                        "xmlns:otm=\"http://xmlns.oracle.com/apps/otm/transmission/v6.4\"", "").
                replaceAll("otm:", "");

        try {
            document = XmlUtil.parseByString(callBackXml);
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage());
            throw new BaseException(ex.getMessage());
        }

        // 接口 id
        String requestIdPath = "/TransmissionReport/TransmissionNo";
        //得到根节点
        Element element = (Element) document.selectSingleNode(requestIdPath);
        //得到根节点的值
        String requestId = element.getText();

        if (StringUtils.isEmpty(requestId)) {
            throw new BaseException("返回的接口id为空");
        }

        // 处理结果
        String returnStatusPath = "/TransmissionReport/ReportStatus";
        //得到根节点
        Element elementReturnStatus = (Element) document.selectSingleNode(returnStatusPath);
        String returnStatus = elementReturnStatus.getText();
        Integer isSuccess = 0;
        if (!StringUtils.isEmpty(returnStatus) && "PROCESSED".equals(returnStatus)) {
            isSuccess = 1;
        }

        // 处理时间
        String processTimePath = "/TransmissionReport/IntegrationLogMessage/DateTimeStamp/GLogDate";
        Element elementProcessTime = (Element) document.selectSingleNode(processTimePath);
        String processTime = elementProcessTime.getText();

        Date otmDate;
        try {
            otmDate = formatter.parse(processTime);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }

        ProcessCallBack processCallBack = new ProcessCallBack();
        processCallBack.setRequestId(requestId);
        processCallBack.setProcessStatus(isSuccess.toString());
        processCallBack.setProcessTime(otmDate);
        processCallBackService.insert(processCallBack);
        return processCallBack;
    }

    /**
     * 查询OTM回调结果
     */
    public ProcessCallBack getProcessResult(String requestId) {
        Wrapper<ProcessCallBack> ew = new EntityWrapper<>();
        ew.eq("request_id", requestId);
        return processCallBackService.selectOne(ew);
    }

    public RestfulResponse<Object> revokeCheckin(RevokeCheckinDTO revokeCheckinDTO) {
        ImportLogHistory importLogHistory = new ImportLogHistory();
        importLogHistory.setSourceSys("otm");
        importLogHistory.setSourceKey(revokeCheckinDTO.getCheckinId().toString());
        importLogHistory.setType("30");
        importLogHistory.setImportStartTime(new Date());
        importLogHistory.setImportEndTime(new Date());
        new Thread(() -> {
            LOGGER.info("开始保存导入日志---------------");
            try {
                iImportLogService.saveImportLogToQiniu(importLogHistory, revokeCheckinDTO.toString());
            } catch (Exception e) {
                LOGGER.error("日志保存失败---------------");
            }
            LOGGER.info("完成日志保存---------------");
        }).start();
        pushRevokeCheckinToSubSys(revokeCheckinDTO);
        return new RestfulResponse<>(0, "", null);
    }


    /**
     * 指令推送子系统
     */
    private void pushRevokeCheckinToSubSys(RevokeCheckinDTO revokeCheckinDTO) {
        new Thread(() -> {
            LOGGER.info("开始保存导入日志---------------");
            try {
                pushSubSystemService.pushToSubSystem(revokeCheckinDTO, IntegrationURIEnum.CANCEL_TRUCK_PUSH.getCode());
            } catch (Exception ex) {
                LOGGER.info(ex.getMessage());
            }
            LOGGER.info("完成日志保存---------------");
        }).start();
    }
}
